﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using App1AppHandler;
using System.Data.SqlClient;
using Reborn_Server.App1AppHandler;

namespace Reborn_WorldServer.App1AppHandler
{
    public class WeaponSkillManager
    {
        private List<WeaponSkill> weaponSkills = new List<WeaponSkill>();
        private Character myCharacter;

        public WeaponSkillManager(Character character)
        {
            myCharacter = character;

            //LOAD ITEM IDs
            SqlConnection MyCon = new SqlConnection(Managers.DBConnectionString);
            SqlCommand SQLCom = new SqlCommand("Characters_WeaponSkills_Select", MyCon);
            SQLCom.CommandType = System.Data.CommandType.StoredProcedure;
            SQLCom.Parameters.AddWithValue("@CharacterID", character.ID);

            MyCon.Open();
            SqlDataReader SDR = SQLCom.ExecuteReader();

            lock (weaponSkills)
            {
                while (SDR.Read())
                {
                    weaponSkills.Add(Managers.GameHandler.WeaponSkills[int.Parse(SDR["WeaponSkillID"].ToString())]);
                }
            }

            SDR.Close();
            MyCon.Close();
            MyCon.Dispose();
        }

        public void addSkill(WeaponSkill weaponSkill)
        {
            lock (weaponSkills)
            {
                weaponSkills.Add(weaponSkill);
                skillsChanged = true;
            }
            if (weaponSkill.Name.ToLower().IndexOf("reach") > -1)
            {
                myCharacter.currentMapItem.parentMap.LootMngr.GetLootInArea(myCharacter);

                myCharacter.Update_Character();
                myCharacter.bagManager.UpdateBag();
                myCharacter.beltManager.UpdateBelt();
            }
        }

        public bool hasSkill(int id_db)
        {
            lock (weaponSkills)
            {
                foreach (WeaponSkill ws in weaponSkills)
                {
                    if (ws.ID_DB == id_db)
                        return true;
                }
            }

            return false;
        }

        public bool useParry(Weapon weapon)
        {
            if (weapon == null)
                return false;

            lock (weaponSkills)
            {
                foreach (WeaponSkill ws in weaponSkills)
                {
                    if (ws.Skill == weapon.Skill && ws.Name.IndexOf("Parry") > -1)
                    {
                        //Get the number of levels over requirement we are
                        int percentToUse = System.Convert.ToInt32(Math.Floor(myCharacter.skillManager.GetCurrentLevel(ws.Skill)) - ws.LevelRequired);

                        //Starts at 8%
                        percentToUse = percentToUse + 8;
                        int requiredMaxValue = percentToUse * 20; //Requires 500 / 1000

                        int maxValue = 2000 + myCharacter.AgilityTotal;  //Require 100 / 1200?
                        requiredMaxValue = requiredMaxValue + myCharacter.AgilityTotal; //Require 300 / 1200?

                        int selectedValue = Managers.GameHandler.random.Next(maxValue);
                        if (selectedValue <= requiredMaxValue)
                            return true;
                        else
                            return false;
                    }
                }
            }

            return false;
        }

        public bool useExcessiveForce(Weapon weapon)
        {
            if (weapon == null)
                return false;

            lock (weaponSkills)
            {
                foreach (WeaponSkill ws in weaponSkills)
                {
                    if (ws.Skill == weapon.Skill && ws.Name.IndexOf("Excessive") > -1)
                    {
                        //Get the number of levels over requirement we are
                        int percentToUse = System.Convert.ToInt32(Math.Floor(myCharacter.skillManager.GetCurrentLevel(ws.Skill)) - ws.LevelRequired);

                        //Starts at 50%
                        percentToUse = percentToUse + 40;
                        int requiredMaxValue = percentToUse * 20; //Requires 500 / 1000

                        int maxValue = 2000 + myCharacter.DexterityTotal;  //Require 100 / 1200?
                        requiredMaxValue = requiredMaxValue + myCharacter.DexterityTotal; //Require 300 / 1200?

                        int selectedValue = Managers.GameHandler.random.Next(maxValue);
                        if (selectedValue <= requiredMaxValue)
                            return true;
                        else
                            return false;
                    }
                }
            }

            return false;
        }

        public int useArmorPiercing(Weapon weapon)
        {
            if (weapon == null)
                return 0;

            lock (weaponSkills)
            {
                foreach (WeaponSkill ws in weaponSkills)
                {
                    if ((ws.Skill == weapon.Skill || (ws.Skill == "Range" && weapon.Range == true && weapon.Melee == false)) && ws.Name.ToLower().IndexOf("armor") > -1)
                    {
                        return SkillManager.AdjustForCombat(System.Convert.ToInt32(Math.Floor(myCharacter.skillManager.GetCurrentLevel(ws.Skill))), 0, myCharacter.DexterityTotal / 2);
                    }
                }
            }

            return 0;
        }


        public bool useStunningBlow(Weapon weapon)
        {
            if (weapon == null)
                return false;

            lock (weaponSkills)
            {
                foreach (WeaponSkill ws in weaponSkills)
                {
                    if ((ws.Skill == weapon.Skill || (ws.Skill == "Range" && weapon.Range == true && weapon.Melee == false)) && ws.Name.ToLower().IndexOf("stunning") > -1)
                    {
                        //Get the number of levels over requirement we are
                        int percentToUse = System.Convert.ToInt32(Math.Floor(myCharacter.skillManager.GetCurrentLevel(ws.Skill)) - ws.LevelRequired);

                        //Starts at 8%
                        percentToUse = percentToUse + 5;
                        int requiredMaxValue = percentToUse * 20; //Requires 100 / 1000

                        int maxValue = 2000 + myCharacter.DexterityTotal;  //Require 100 / 1200?
                        requiredMaxValue = requiredMaxValue + myCharacter.DexterityTotal; //Require 300 / 1200?

                        int selectedValue = Managers.GameHandler.random.Next(maxValue);
                        if (selectedValue <= requiredMaxValue)
                            return true;
                        else
                            return false;
                    }
                }
            }

            return false;
        }

        public bool usePerfectSwing(Weapon weapon)
        {
            if (weapon == null)
                return false;

            lock (weaponSkills)
            {
                foreach (WeaponSkill ws in weaponSkills)
                {
                    if ((ws.Skill == weapon.Skill || (ws.Skill == "Range" && weapon.Range == true && weapon.Melee == false)) && ws.Name.ToLower().IndexOf("perfect") > -1)
                    {
                        //Get the number of levels over requirement we are
                        int percentToUse = System.Convert.ToInt32(Math.Floor(myCharacter.skillManager.GetCurrentLevel(ws.Skill)) - ws.LevelRequired);

                        //Starts at 8%
                        percentToUse = percentToUse + 8;
                        int requiredMaxValue = percentToUse * 20; //Requires 100 / 1000

                        int maxValue = 2000 + myCharacter.DexterityTotal;  //Require 100 / 1200?
                        requiredMaxValue = requiredMaxValue + myCharacter.DexterityTotal; //Require 300 / 1200?

                        int selectedValue = Managers.GameHandler.random.Next(maxValue);
                        if (selectedValue <= requiredMaxValue)
                            return true;
                        else
                            return false;
                    }
                }
            }

            return false;
        }

        public bool useCriticalDamage(Weapon weapon)
        {
            if (weapon == null)
                return false;

            lock (weaponSkills)
            {
                foreach (WeaponSkill ws in weaponSkills)
                {
                    if ((ws.Skill == weapon.Skill || (ws.Skill == "Range" && weapon.Range == true && weapon.Melee == false)) && ws.Name.IndexOf("Critical") > -1)
                    {
                        //Get the number of levels over requirement we are
                        int percentToUse = System.Convert.ToInt32(Math.Floor(myCharacter.skillManager.GetCurrentLevel(ws.Skill)) - ws.LevelRequired);

                        //Starts at 10%
                        percentToUse = percentToUse + 8;
                        int requiredMaxValue = percentToUse * 20; //Requires 100 / 1000

                        int maxValue = 2000 + myCharacter.DexterityTotal;  //Require 100 / 1200?
                        requiredMaxValue = requiredMaxValue + myCharacter.DexterityTotal; //Require 300 / 1200?

                        int selectedValue = Managers.GameHandler.random.Next(maxValue);
                        if (selectedValue <= requiredMaxValue)
                            return true;
                        else
                            return false;
                    }
                }
            }

            return false;
        }

        public Weapon getDualWeildWeapon(Weapon usingWeapon)
        {
            //Cant duel weild if we're using an invalid weapon to begin with
            if (usingWeapon == null)
                return null;

            //Cant duel weild if the weapon we're using isnt in our right hand (This shouldnt happen, its just incase)
            if (myCharacter.RightHand != usingWeapon)
                return null;

            Weapon leftHandWeapon = null;
            if (myCharacter.LeftHand != null && myCharacter.LeftHand is Weapon)
                leftHandWeapon = (Weapon)myCharacter.LeftHand;

            //Cant duel weild with no left hand weapon, or weapon in left hand is not correct slot
            if (leftHandWeapon == null || !(leftHandWeapon.Slot == "LeftHand" || leftHandWeapon.Slot == "EitherHand"))
                return null;

            if (leftHandWeapon.DmgLow < 1 || leftHandWeapon.Melee == false)
                return null;

            //Cant dual weild if we dont meet the level requirements of the left hand weapon
            if (myCharacter.equipManager.MeetsRequirements(leftHandWeapon) == false)
                return null;

            if (useDualWeildSkill(leftHandWeapon) == false)
                return null;

            return leftHandWeapon;
        }

        private bool useDualWeildSkill(Weapon weapon)
        {
            if (weapon == null)
                return false;

            lock (weaponSkills)
            {
                foreach (WeaponSkill ws in weaponSkills)
                {
                    if (ws.Skill == weapon.Skill && ws.Name.IndexOf("Dual Weild") > -1)
                    {
                        //Get the number of levels over requirement we are
                        int percentToUse = System.Convert.ToInt32(Math.Floor(myCharacter.skillManager.GetCurrentLevel(ws.Skill)) - ws.LevelRequired);
                        
                        //Starts at 10%
                        percentToUse = percentToUse + 8; 
                        int requiredMaxValue = percentToUse * 20; //Requires 100 / 1000

                        int maxValue = 2000 + myCharacter.DexterityTotal;  //Require 100 / 1200?
                        requiredMaxValue = requiredMaxValue + myCharacter.DexterityTotal; //Require 300 / 1200?

                        int selectedValue = Managers.GameHandler.random.Next(maxValue);
                        if (selectedValue <= requiredMaxValue)
                            return true;
                        else
                            return false;
                    }
                }
            }

            return false;
        }

        // Checks if the player has extended reach skill for this weapon type.
        // Currently this is used when we send out item XML to toggle the Range attributes.
        public bool hasExtendedReach(Weapon weapon)
        {
            if (weapon == null)
                return false;

            lock (weaponSkills)
            {
                foreach (WeaponSkill ws in weaponSkills)
                {
                    if (ws.Skill == weapon.Skill && ws.Name.ToLower().IndexOf("reach") > -1)
                        return true;
                }
            }

            return false;
        }

        public bool useInstantRush(Weapon weapon)
        {
            if (weapon == null)
                return false;

            lock (weaponSkills)
            {
                foreach (WeaponSkill ws in weaponSkills)
                {
                    if (ws.Skill == weapon.Skill && ws.Name.ToLower().IndexOf("flying") > -1)
                        return true;
                }
            }

            return false;
        }

        public bool useExceptionalBalance()
        {
            //Currently only checking for right hand because only 2H blunt has this skill
            Weapon rightHandWeapon = null;

            if (myCharacter.RightHand != null && myCharacter.RightHand is Weapon)
            {
                rightHandWeapon = (Weapon)myCharacter.RightHand;

                if (rightHandWeapon.Slot == "2Hand" && myCharacter.LeftHand != null)
                    rightHandWeapon = null;
            }

            if (rightHandWeapon == null)
                return false;

            lock (weaponSkills)
            {
                foreach (WeaponSkill ws in weaponSkills)
                {
                    if (ws.Name.ToLower().IndexOf("balance") > -1 && ws.Skill == rightHandWeapon.Skill)
                    {
                        //Get the number of levels over requirement we are
                        int percentToUse = System.Convert.ToInt32(Math.Floor(myCharacter.skillManager.GetCurrentLevel(ws.Skill)) - ws.LevelRequired);

                        //Starts at 50%
                        percentToUse = percentToUse + 50;
                        int requiredMaxValue = percentToUse * 20; //Requires 500 / 1000

                        int maxValue = 2000 + myCharacter.AgilityTotal;  //Require 100 / 1200?
                        requiredMaxValue = requiredMaxValue + myCharacter.AgilityTotal; //Require 300 / 1200?

                        int selectedValue = Managers.GameHandler.random.Next(maxValue);
                        if (selectedValue <= requiredMaxValue)
                            return true;
                        else
                            return false;
                    }
                }
            }

            return false;
        }

        public bool useShieldMastery(Weapon weapon)
        {
            if (weapon == null)
                return false;

            //No good way to identify shield... check slot, skill, and defense
            if (weapon.Slot != "LeftHand")
                return false;

            if (weapon.Skill != "")
                return false;

            if (weapon.Defense == 0)
                return false;

            lock (weaponSkills)
            {
                foreach (WeaponSkill ws in weaponSkills)
                {
                    if (ws.Name.ToLower().IndexOf("shield") > -1)
                    {
                        return true;
                    }
                }
            }

            return false;
        }

        public bool useDoubleAttackSkill(Weapon weapon)
        {
            if (weapon == null)
                return false;

            lock (weaponSkills)
            {
                foreach (WeaponSkill ws in weaponSkills)
                {
                    if ((ws.Skill == weapon.Skill || (weapon.Range == true && weapon.Melee == false && ws.Skill == "Range")) && ws.Name.IndexOf("Double") > -1)
                    {
                        //Get the number of levels over requirement we are
                        int percentToUse = System.Convert.ToInt32(Math.Floor(myCharacter.skillManager.GetCurrentLevel(ws.Skill)) - ws.LevelRequired);

                        //Starts at 10%
                        percentToUse = percentToUse + 8;
                        int requiredMaxValue = percentToUse * 20; //Requires 100 / 1000

                        int maxValue = 2000 + myCharacter.DexterityTotal;  //Require 100 / 1200?
                        requiredMaxValue = requiredMaxValue + myCharacter.DexterityTotal; //Require 300 / 1200?

                        int selectedValue = Managers.GameHandler.random.Next(maxValue);
                        if (selectedValue <= requiredMaxValue)
                            return true;
                        else
                            return false;
                    }
                }
            }

            return false;
        }


        private bool skillsChanged = false;
        public void saveSkills()
        {
            lock (weaponSkills)
            {
                if (skillsChanged == true)
                {
                    skillsChanged = false;

                    SqlConnection MyCon = new SqlConnection(Managers.DBConnectionString);
                    MyCon.Open();
                    SqlTransaction MyTrans = MyCon.BeginTransaction();

                    SqlCommand SQLCom = new SqlCommand();
                    SQLCom.CommandType = System.Data.CommandType.StoredProcedure;
                    SQLCom.Connection = MyCon;
                    SQLCom.Transaction = MyTrans;

                    try
                    {
                        SQLCom.CommandText = "Characters_WeaponSkills_DeletePerCharacterID";
                        SQLCom.Parameters.AddWithValue("@CharacterID", myCharacter.ID);
                        SQLCom.ExecuteNonQuery();

                        SQLCom.CommandText = "Characters_WeaponSkills_Insert";

                        SQLCom.Parameters.Add("@WeaponSkillID", System.Data.SqlDbType.Int);

                        foreach (WeaponSkill ws in weaponSkills)
                        {
                            SQLCom.Parameters["@WeaponSkillID"].Value = ws.ID_DB;
                            SQLCom.ExecuteNonQuery();
                        }

                        MyTrans.Commit();
                    }
                    catch
                    {
                        MyTrans.Rollback();
                    }
                    finally
                    {
                        MyCon.Close();
                        MyCon.Dispose();
                    }
                }
            }
        }
    }
}
